home *** CD-ROM | disk | FTP | other *** search
- Path: news.delphi.com!usenet
- From: Derek Harmon <stonelight@delphi.com>
- Newsgroups: comp.lang.c
- Subject: Re: New C Programmer Has A Problem
- Date: Mon, 29 Jan 96 11:43:57 -0500
- Organization: Delphi (info@delphi.com email, 800-695-4005 voice)
- Message-ID: <ZtBK4dl.stonelight@delphi.com>
- References: <4ehpa3$6kl@nntp.novia.net>
- NNTP-Posting-Host: bos1g.delphi.com
- X-To: Tony Syslo <tsyslo@oasis.novia.net>
-
-
- Quoting a message by tsyslo@oasis.novia.net dated <29-Jan-1996>:
- > I have a question on C... why isn't this program working?!
-
- This isn't a very good way to start off, Tony. It would help to know
- where you suspect the problem might be. I'll assume it compiles okay,
- generating a "Couldn't open the file" message isn't the problem, nor are
- you having any problems reading STDIN with scanf() (a dangerous practice
- IMO).
-
- Let's have a look at your program:
-
- > void main();
- >
- > char *name;
- > int age;
-
- Name is a pointer. It points to a string of characters, terminated
- by a Null ('/0'). It's size is implementation-dependent, but is generally
- 2-bytes or 4-bytes. In most cases, C allows you the freedom to treat a
- (char *) as an array of char, but I suspect you get caught in a trap due
- to this later. I also don't see name initially allocated any memory,
- either directly or indirectly. So for now I suggest:
-
- : char name[20];
- : int age;
-
- > long bytes_written;
- > long bytes_read;
-
- I didn't see anyplace in your code where these are initialized to
- (presumably) zero.
-
- > printf("\nEnter your age: "); scanf("%d",age);
-
- This might not work, because age is an integer, not a pointer to an
- integer. It was okay for name, because name was a pointer to a char..
- but not good for age. I would reccommend:
-
- : printf("\nEnter your age: "); scanf("%d", &age);
-
- The &-operator tells C to use the address-of age, which is what scanf()
- wants. I suspect your program probably blew-up here.
-
- > /* We have now opened a file, and are ready to start writing: */
- > bytes_written=Write(file_handle,name,sizeof(name));
- > bytes_written=bytes_written+Write(file_handle,age,sizeof(age));
- >
-
- Here there are 2 problems. write() is similar to scanf() in that it
- requires a file handle, a pointer addressing an element of data, and how many
- bytes it should write beginning at that location. So, while the first line
- works in this regard for name (since it is a pointer), the second will write
- not the value of age (if age were 8, say) but whatever it finds at address
- 0000:0008. Which, on a Unix would probably get you a Segmentation fault,
- and elsewhere would get you garbage, but would not get you 8.
-
- Unfortunately, the first line isn't totally fault-free either. If name
- were an array of char, say, char name[20], then sizeof(name) would be 20.
- That would be alright. However, as name is a POINTER to a char, and a
- pointer is 2 or 4 bytes long, sizeof(name) is 2 or 4. printf("%s",name)
- might be "Humperdink", strlen(name) would be 10, but sizeof(name) will
- always be 2 or 4. There are 2 ways around this: (a) use strlen(name)
- instead of sizeof(name), but I would rule this out as it turns your fixed-
- length field file into a more complicated variable-length field file.
- (b) make name an array of char.
-
- : bytes_written = Write(file_handle,name,sizeof(name));
- : bytes_written += Write(file_handle,&age,sizeof(age));
-
- > if(bytes_written!=sizeof(name)+sizeof(age))
- : /* could not save list */
- : else
- : /* save is GOOD, save is GOOD! */
-
- Same thing, but will work the first time through when name is an array.
-
- > printf("Memory cleared!\n");
- > name="";
- > age=0;
-
- If, though, you are clearing memory (perhaps to include this in a loop
- sometime in the future), you should include bytes_written (and read) = 0.
- Otherwise, for tests after the first, bytes_written will have accumulated
- a value greater than sizeof(name) + sizeof(age) above.
-
- Also, name="" is a dangerous (BASIC-like) way to nullify a string in C,
- although it may work in this instance (equiv to saying name[0] = '\0').
-
- > bytes_read=Read(file_handle,name,sizeof(name));
- > bytes_read=bytes_read+Read(file_handle,age,sizeof(age));
-
- : bytes_read = Read(file_handle,name,sizeof(name));
- : bytes_read += Read(file_handle,&age,sizeof(age));
-
- Again, same thing with read() requiring a buffer to read the data into,
- age is a integer, &age is the address of an integer, so use &age instead.
-
- > Program END:
-
- In summary,
-
- 1) Many C functions require a "buffer" which they write/read data to/from.
- If this is the case, you must either pass them a variable that is a pointer
- (ie, a char * or array) in which case you just use the variable name. Or,
- you can pass them a variable that is not a pointer (an int, char, struct)
- but you must prefix it with the address-of operator, &. This is often
- a case with I/O functions. Check the prototypes in any headers, ie:
-
- int write(int handle, void *buf, unsigned len);
- ^
- \___ asterisk indicates expecting a pointer.
-
- 2) When using strings, be careful. Strings in C are very TWICKY!
-
- > Any help if MUCH appreciated...
-
- Hope this helps.
-
- - Stone
- --
- ... The generation of random numbers is too important to be left to chance.
-
-